<?php

namespace app\models;

use http\Exception\RuntimeException;

class Matrix
{
    private $data = array(array());

    private $width = 0;

    private $height = 0;

    public function getData() {
        return $this->data;
    }

    public function getWidth() {
        return $this->width;
    }

    public function getHeight() {
        return $this->height;
    }

    public function initWithMatrix($matrix) {
        $this->receiveWidthAndHeight($matrix);
        $this->data = $matrix;
    }

    public function initWithSizes($i, $j) {
        $this->height = $i;
        $this->width = $j;

        $this->data = array();

        for ($ci = 0; $ci < $i; $ci++) {
            $newItem = array();

            for ($cj = 0; $cj < $j; $cj++)
                $newItem[] = 0.;

            $this->data[] = $newItem;
        }
    }

    public function get($i, $j) {
        return $this->data[$i][$j];
    }

    public function set($i, $j, $value) {
        $this->data[$i][$j] = $value;
    }

    private function receiveWidthAndHeight($matrix) {
        $currentHeight = sizeof($matrix);
        $currentWidth = $currentHeight > 0 ? sizeof($matrix[0]) : 0;

        $this->validate($matrix, $currentHeight, $currentWidth);

        $this->height = $currentHeight;
        $this->width = $currentWidth;
    }

    private function validate($matrix, $height, $width) {
        if ($height > 0 && $width == 0)
            throw new RuntimeException('IncorrectMatrixException');

        if (sizeof($matrix) != $height)
            throw new RuntimeException('IncorrectMatrixException');

        for ($i = 0; $i < sizeof($matrix); $i++) {
            $row = $matrix[$i];

            if (sizeof($row) != $width)
                throw new RuntimeException('IncorrectMatrixException');
        }
    }

    public static function multiply($matrix1, $matrix2) {
        if ($matrix1->getWidth() != $matrix2->getHeight())
            throw new RuntimeException('MatrixMultiplicationException');

        $newMatrix = new Matrix();
        $newMatrix->initWithSizes($matrix1->getHeight(), $matrix2->getWidth());

        for ($i = 0; $i < $matrix1->getHeight(); $i++) {
            for ($j = 0; $j < $matrix2->getWidth(); $j++) {
                $current = 0.0;

                for ($k = 0; $k < $matrix1->getWidth(); $k++)
                    $current += $matrix1->get($i, $k) * $matrix2->get($k, $j);

                $newMatrix->set($i,$j, $current);
            }
        }

        return $newMatrix;
    }


}